using System;
using System.Globalization;
using System.Xml;

namespace Common
{
    /// <summary>
    /// 一些类型转换的函数。Int IsMy_yxh
    /// </summary>
    public static partial class ValueProc
    {
        public enum CPUSizeEnum
        {
            Bytes,
            KB,
            MB,
            GB,
            TB
        }
        public class CPUSizeCls
        {
            public double Value { get; set; }
            public CPUSizeEnum Unit { get; set; }
        }
        public static string GetMySize(int BytesOfSize)
        {
            CPUSizeCls size = GetMySize(new CPUSizeCls() { Value = BytesOfSize, Unit = CPUSizeEnum.Bytes });
            return string.Format(@"{0} {1}", size.Value.ToString("0.##"), size.Unit.ToString());
        }
        public static CPUSizeCls GetMySize(CPUSizeCls Value)
        {
            if (Value.Unit == CPUSizeEnum.TB || Value.Value <= 1024)
            {
                return Value;
            }
            if (Value.Value > 1024)
            {
                Value.Value = Value.Value / 1024;
                Value.Unit = (Value.Unit.GetInt() + 1).ToEnum<CPUSizeEnum>();
                Value = GetMySize(Value);
            }
            return Value;
        }

        /// <summary>
        /// 得到 对象 的 布尔类型的值。
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static bool GetBool(this object Value)
        {
            return GetBool(Value, false);
        }

        /// <summary>
        /// 得到对象的 Int 类型的值 。
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static int GetInt(this object Value)
        {
            return GetInt(Value, 0);
        }

        /// <summary>
        /// 得到对象的 String 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static string GetString(this object Value)
        {
            return GetString(Value, string.Empty);
        }

        /// <summary>
        /// 得到对象的 Decimal 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static decimal GetDecimal(this object Value)
        {
            return GetDecimal(Value, 0);
        }

        /// <summary>
        /// 得到对象的 Float 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static float GetFloat(object Value)
        {
            return GetFloat(Value, 0f);
        }

        /// <summary>
        /// 得到对象的 Long 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static long GetLong(object Value)
        {
            return GetLong(Value, 0);
        }

        /// <summary>
        /// 得到对象的 Bool 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <param name="defaultValue">如果转换失败，返回的默认值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static bool GetBool(this object Value, bool defaultValue)
        {
            if (Value == null) return defaultValue;
            if (Value is string && Value.GetString().HasValue() == false) return defaultValue;

            if ((Value is string) == false && (Value is IConvertible) == true)
            {
                if (Value is DBNull) return defaultValue;

                try
                {
                    return (Value as IConvertible).ToBoolean(CultureInfo.CurrentCulture);
                }
                catch { }
            }

            if (Value is string)
            {
                if (Value.GetString() == "0") return false;
                if (Value.GetString() == "1") return true;
                if (Value.GetString().ToLower() == "yes") return true;
                if (Value.GetString().ToLower() == "no") return false;
            }
            if (Value.GetInt(0) != 0) return true;

            bool retVal = defaultValue;
            if (bool.TryParse(Value.GetString(), out retVal))
            {
                return retVal;
            }
            else return defaultValue;
        }

        /// <summary>
        /// 得到对象的 Int 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <param name="defaultValue">如果转换失败，返回的默认值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static int GetInt(this object Value, int defaultValue)
        {
            if (Value == null) return defaultValue;
            if (Value is string && Value.GetString().HasValue() == false) return defaultValue;

            if (Value is DBNull) return defaultValue;

            if ((Value is string) == false && (Value is IConvertible) == true)
            {
                return (Value as IConvertible).ToInt32(CultureInfo.CurrentCulture);
            }

            int retVal = defaultValue;
            if (int.TryParse(Value.ToString(), NumberStyles.Any, CultureInfo.CurrentCulture, out retVal))
            {
                return retVal;
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 得到对象的 String 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <param name="defaultValue">如果转换失败，返回的默认值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static string GetString(this object Value, string defaultValue)
        {
            if (Value == null) return defaultValue;
            string retVal = defaultValue;
            try
            {
                if (Value is XmlAttribute)
                {
                    if (Value != null)
                    {
                        retVal = (Value as XmlAttribute).Value;
                    }
                    else retVal = string.Empty;
                }
                else
                {
                    retVal = Value.ToString();
                }
            }
            catch
            {
                return defaultValue;
            }
            return retVal;
        }

        /// <summary>
        /// 得到对象的 Decimal 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <param name="defaultValue">如果转换失败，返回的默认值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static decimal GetDecimal(this object Value, decimal defaultValue)
        {
            if (Value == null) return defaultValue;
            if (Value is string && Value.GetString().HasValue() == false) return defaultValue;

            if (Value is DBNull) return defaultValue;

            if ((Value is IConvertible) == true && (Value is string) == false)
            {
                return (Value as IConvertible).ToDecimal(CultureInfo.CurrentCulture);
            }

            decimal retVal = defaultValue;
            if (decimal.TryParse(Value.ToString(), NumberStyles.Any, CultureInfo.CurrentCulture, out retVal))
            {
                return retVal;
            }
            else return defaultValue;
        }

        /// <summary>
        /// 得到对象的 Long 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <param name="defaultValue">如果转换失败，返回的默认值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static long GetLong(object Value, long defaultValue)
        {
            if (Value == null) return defaultValue;
            if (Value is string && Value.GetString().HasValue() == false) return defaultValue;

            if (Value is DBNull) return defaultValue;

            if ((Value is string) == false && (Value is IConvertible) == true)
            {
                return (Value as IConvertible).ToInt64(CultureInfo.CurrentCulture);
            }


            long retVal = defaultValue;
            if (long.TryParse(Value.ToString(), out retVal))
            {
                return retVal;
            }
            else return defaultValue;
        }

        /// <summary>
        /// 得到对象的 Float 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <param name="defaultValue">如果转换失败，返回的默认值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static float GetFloat(object Value, float defaultValue)
        {
            if (Value == null) return defaultValue;
            if (Value is string && Value.GetString().HasValue() == false) return defaultValue;

            if (Value is DBNull) return defaultValue;

            if ((Value is string) == false && (Value is IConvertible) == true)
            {
                return (Value as IConvertible).ToSingle(CultureInfo.CurrentCulture);
            }


            float retVal = defaultValue;
            if (float.TryParse(Value.GetString(), out retVal))
            {
                return retVal;
            }
            else return defaultValue;
        }

        /// <summary>
        /// 得到对象的 DateTime 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static DateTime GetDateTime(this object Value)
        {
            return GetDateTime(Value, DateTime.MinValue);
        }

        /// <summary>
        /// 得到对象的 DateTime 类型的值
        /// </summary>
        /// <param name="Value">要转换的值</param>
        /// <param name="defaultValue">如果转换失败，返回的默认值</param>
        /// <returns>如果对象的值可正确返回， 返回对象转换的值 ，否则， 返回默认值 。</returns>
        public static DateTime GetDateTime(this object Value, DateTime defaultValue)
        {
            if (Value == null) return defaultValue;

            if (Value is DBNull) return defaultValue;

            string strValue = Value as string;
            if (strValue == null && (Value is IConvertible))
            {
                return (Value as IConvertible).ToDateTime(CultureInfo.CurrentCulture);
            }
            if (strValue != null)
            {
                strValue = strValue
                    .Replace("年", "-")
                    .Replace("月", "-")
                    .Replace("日", "-")
                    .Replace("点", ":")
                    .Replace("时", ":")
                    .Replace("分", ":")
                    .Replace("秒", ":")
                      ;
            }
            DateTime dt = defaultValue;
            if (DateTime.TryParse(Value.GetString(), out dt))
            {
                return dt;
            }

            return defaultValue;
        }

        /// <summary>
        /// 检测 Value 是否包含有效的值 。 IsMy_yxh
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static bool HasValue(this string Value)
        {
            if (Value != null)
            {
                return !string.IsNullOrEmpty(Value.ToString());
            }
            else return false;
        }

        /// <summary>
        ///	去除开头的字符串。 
        /// </summary>
        /// <param name="Value">
        /// </param>
        /// <param name="RemoveStart">
        /// </param>
        /// <returns>
        /// </returns>
        public static string TrimStart(this string Value, string RemoveStart)
        {
            if (Value.StartsWith(RemoveStart))
            {
                Value = Value.Substring(RemoveStart.Length);

                if (Value.StartsWith(RemoveStart))
                {
                    Value = Value.TrimStart(RemoveStart);
                }
            }

            return Value;
        }

        /// <summary>
        /// 去除结尾的字符串
        /// </summary>
        /// <param name="Value">
        /// </param>
        /// <param name="RemoveEnd">
        /// </param>
        /// <returns>
        /// </returns>
        public static string TrimEnd(this string Value, string RemoveEnd)
        {
            if (Value.EndsWith(RemoveEnd))
            {
                Value = Value.Remove(Value.Length - RemoveEnd.Length);

                if (Value.EndsWith(RemoveEnd))
                {
                    Value = Value.TrimEnd(RemoveEnd);
                }
            }

            return Value;
        }
        public static string TrimWithPair(this string Value, string RemoveStart, string RemoveEnd)
        {
            return TrimWithPair(Value, RemoveStart, RemoveEnd, StringComparison.CurrentCulture);
        }
        /// <summary>
        /// 结队去除，比如去除 () {} [] , 或 &lt;a>t&lt;/a> 等
        /// </summary>
        /// <param name="Value">
        /// </param>
        /// <param name="RemoveStart">
        /// </param>
        /// <param name="RemoveEnd">
        /// </param>
        /// <returns>
        /// </returns>
        public static string TrimWithPair(this string Value, string RemoveStart, string RemoveEnd, StringComparison Compare)
        {
            if (Value.HasValue() == false || RemoveStart.HasValue() == false || RemoveEnd.HasValue() == false)
                return Value;

            Value = Value.Trim();
            RemoveStart = RemoveStart.Trim();
            RemoveEnd = RemoveEnd.Trim();

            if (Value.StartsWith(RemoveStart, Compare) && Value.EndsWith(RemoveEnd, Compare))
            {
                Value = Value.Substring(RemoveStart.Length);
                Value = Value.Remove(Value.Length - RemoveEnd.Length);

                if (Value.StartsWith(RemoveStart) && Value.EndsWith(RemoveEnd))
                {
                    Value = TrimWithPair(Value, RemoveStart, RemoveEnd, Compare);
                }
            }

            return Value.Trim();
        }

        public static Guid GetGuid(string GuidValue)
        {
            try
            {
                return new Guid(GuidValue);
            }
            catch { return Guid.Empty; }
        }

        public static T GetValueOrDefault<T>(this Nullable<T> Value) where T : struct
        {
            if (Value.HasValue) return Value.Value;
            else return default(T);
        }
    }
}
